/* file: grammar.mly */


%{
  open Type
%}

%token <int> INTEGER
%token <float> FLOAT
%token <bool> BOOLEAN
%token <string> VAR STRING OPERATOR_UNARY OPERATOR_BIN 
%token NEWLINE COMMA
%token EQUAL
%token LPAREN RPAREN
%token LBRACE RBRACE
%token LBRACKET RBRACKET
%token IF ELSIF ELSE FOR IN DO WHILE END DOT
%token DEF RETURN
%token PRINT 

%right EQUAL


%start expr
%type <Type.expr> expr

%% /* Grammar rules and actions follow */
expr:
	  NEWLINE expr											{ $2 }
	| struct_if      										{ Struct_If($1) }
	| struct_while											{ $1 }
	| struct_for											{ $1 }
	| assignment   											{ $1 }
	| print													{ $1 }
	| decl_function											{ $1 }
	| appel_function										{ $1 }

print:
	PRINT print_internal									{ Print($2) }

print_internal:
	  exp 													{ [$1] }
	| exp COMMA print_internal								{ $1::$3 }

exp:
	  INTEGER												{ Int($1) }
	| FLOAT													{ Float($1) }
	| STRING												{ String($1) }
	| BOOLEAN												{ Bool($1) }
	| VAR													{ Var($1) }
	| VAR LBRACKET exp RBRACKET								{ Array_index($1, $3) }
	| LPAREN exp RPAREN										{ Parenthesized($2) }
	| exp OPERATOR_BIN exp									{ Binary($1, $2, $3) }
	| OPERATOR_UNARY exp									{ Unary($1, $2) }
	| LBRACKET array_block RBRACKET							{ Array($2) }
	| appel_function										{ $1 }




array_block:
	  exp													{ [$1] }
	| exp COMMA array_block									{ $1::$3 }

assignment:
	  exp EQUAL exp											{ Assignment($1, $3) }



struct_if:
	  IF LPAREN exp RPAREN LBRACE block 			  		{ [If($3, $6)] }
	| IF LPAREN exp RPAREN LBRACE block struct_elsif	{ If($3, $6)::$7 }
	| IF LPAREN exp RPAREN LBRACE block struct_else		{ If($3, $6)::$7 }

struct_elsif:
	  ELSIF LPAREN exp RPAREN LBRACE block				  	{ [Elsif($3, $6)] }
	| ELSIF LPAREN exp RPAREN LBRACE block struct_elsif	{ Elsif($3, $6)::$7 }
	| ELSIF LPAREN exp RPAREN LBRACE block struct_else	{ Elsif($3, $6)::$7 }

struct_else:
	  ELSE LBRACE block										{ [Else($3)] }

block:
	  RBRACE												{ [] }
	| expr block			    	    					{ $1 :: $2 }


/* while */
struct_while:
	  WHILE LPAREN exp RPAREN NEWLINE block_loop			{ While($3, $6) }

/* for */
struct_for:
	  FOR VAR IN LPAREN exp DOT DOT exp RPAREN	 NEWLINE DO NEWLINE block_loop
		                                            { For(Var($2), $5, $8, $13) }

block_loop:
	  NEWLINE END											{ [] }
	| expr block_loop										{ $1::$2 }



/* declaration de fonction */
decl_function:
	  DEF VAR LPAREN arg_list_dec RPAREN block_function
		                                         { Decl_Function(Var($2), $4, $6) }
	| DEF VAR LPAREN RPAREN block_function     { Decl_Function(Var($2), [], $5) }



arg_list_dec:
	  VAR													{ [Var($1)] }
	| VAR COMMA arg_list									{ (Var($1))::$3 }

arg_list:
	  exp													{ [$1] }
	| exp COMMA arg_list									{ $1::$3 }

block_function:
	  END													{ [] }
	| NEWLINE END											{ [] }
	| RETURN exp block_function								{ Return($2)::$3 }
	| NEWLINE RETURN exp block_function						{ Return($3)::$4 }

	| expr block_function									{ $1::$2 }

/* appel de fonction, NOTE ne pas l'appeller "function" : 
   reservé par ocamlyacc ! */
appel_function:
	  VAR LPAREN arg_list RPAREN							{ Function(Var($1), $3) }
	| VAR LPAREN RPAREN										{ Function(Var($1), []) }


%%

